package com.suray.system.run.impl;

import com.suray.basic.wcs.path.enums.NodeType;
import com.suray.basic.wcs.plc.pojo.oper.lifter.LifterOper;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.system.run.convery.ConveryMonitor;
import com.suray.system.run.core.*;
import com.suray.system.run.data.RgvInformation;
import com.suray.system.run.data.SystemMonitorInformation;
import com.suray.system.run.data.mysql.analyze.MonitorDataStore;
import com.suray.system.run.lifter.LifterMonitor;
import com.suray.system.run.rgv.RgvMonitor;
import com.suray.system.run.task.TaskMonitor;
import com.suray.system.run.type.DeviceType;
import com.suray.system.run.type.TaskType;
import com.suray.system.run.util.ExecTaskTime;
import com.suray.wcs.service.init.SystemInit;
import com.suray.wcs.service.pojo.Rgv;
import com.suray.wcs.service.system.service.impl.NodeDBServiceImpl;

import java.util.ArrayList;
import java.util.List;

public class SystemMonitor {
    NodeDBServiceImpl nodeDBService = SpringContextHolder.getBean(NodeDBServiceImpl.class);

    protected List<RgvMonitor> rgvMonitors;
    protected List<LifterMonitor> lifterMonitors;
    protected List<ConveryMonitor> converyMonitors;
    protected TaskMonitor taskMonitor;
    protected SystemMonitorInformation monitorInformation;

    public static MonitorDataStore monitorDataStore;

    public void init() {
        monitorInformation = new SystemMonitorInformation();
        rgvMonitors = new ArrayList<>();
        lifterMonitors = new ArrayList<>();
        monitorDataStore = new MonitorDataStore();

        rgvRegister();
        lifterRegister();
        converyRegister();
        taskRegister();

        rgvMonitors.forEach(rgvMonitor -> {
            rgvMonitor.init();
        });
    }

    private void taskRegister() {
        taskMonitor = new TaskMonitor();
        taskMonitor.init();
    }

    /**
     * 获取小车当前故障信息
     * @param series
     * @return
     */
    public ErrorDescription findDeviceErrorDes(String series) {
        RgvInformation rgvInformation = monitorInformation.getRgvs().get(series);
        if (rgvInformation == null) {
            return null;
        }

        return rgvInformation.getErrorDescription();
    }

    /**
     * 获取小车当前离线信息
     * @param series
     * @return
     */
    public OfflineDescription findDeviceOffLineDes(String series) {
        RgvInformation rgvInformation = monitorInformation.getRgvs().get(series);
        if (rgvInformation == null) {
            return null;
        }

        return rgvInformation.getOffLineDescription();
    }

    /**
     * 获取小车当前离线信息
     * @param series
     * @return
     */
    public ChargeInfo findDeviceChargeInfo(String series) {
        RgvInformation rgvInformation = monitorInformation.getRgvs().get(series);
        if (rgvInformation == null) {
            return null;
        }

        return rgvInformation.getChargeInfo();
    }

    /**
     * 获取小车当前任务信息
     * @param series
     * @return
     */
    public ExecTaskTime findDeviceTaskInfo(String series) {
        RgvInformation rgvInformation = monitorInformation.getRgvs().get(series);
        if (rgvInformation == null) {
            return null;
        }

        return rgvInformation.getExecTaskTime();
    }


    /**
     * 获取小车当前充电信息
     * @param series
     * @return
     */
    public LowBatteryDescription findLowBatteryInfo(String series) {
        RgvInformation rgvInformation = monitorInformation.getRgvs().get(series);
        if (rgvInformation == null) {
            return null;
        }

        return rgvInformation.getLowBatteryDescription();
    }

    /**
     * 小车注册
     */
    private void rgvRegister() {
        for (Rgv rgv : SystemInit.RGVS) {
            rgvRegister(rgv);
        }
    }

    private void rgvRegister(Rgv rgv) {
        RgvInformation rgvInformation = monitorInformation.getRgvInformation(rgv.getSeries());
        monitorDataStore.insertDevice(rgv.getSeries());
        RgvMonitor rgvMonitor = new RgvMonitor(rgv, rgvInformation, monitorDataStore);
        rgvMonitors.add(rgvMonitor);
    }

    /**
     * 提升机注册
     */
    private void lifterRegister() {
//        Plc.deviceLifterCoordMap.values().forEach(deviceBase -> {
//            if (deviceBase instanceof LifterOper && deviceBase.getLocation().equals(Location.INSIDE)) {
//                LifterOper lifterOper = (LifterOper) deviceBase;
//                lifterRegister(lifterOper);
//            }
//        });
    }

    private void lifterRegister(LifterOper lifterOper) {
//        LifterInformation lifterInformation = monitorInformation.getLifterInformation(lifterOper.getSeries());
//        monitorDataStore.insertDevice(lifterOper.getSeries());
//        LifterMonitor lifterMonitor = new LifterMonitor(lifterOper, lifterInformation, monitorDataStore);
//        lifterMonitors.add(lifterMonitor);
    }

    /**
     * 输送线注册
     */
    private void converyRegister() {

    }

    public void run() {
        rgvMonitors.forEach(rgvMonitor -> {
            rgvMonitor.run();
        });

        taskMonitor.run();
    }

    /**
     * 获取设备数量
     * @param deviceType
     * @return
     */
    public int getDeviceNum(DeviceType deviceType) {
        if (deviceType == DeviceType.RGV4) {
            return rgvMonitors.size();
        } else if (deviceType == DeviceType.CONVERY) {
            return converyMonitors.size();
        } else if (deviceType == DeviceType.LIFTER_PLC) {
            return lifterMonitors.size();
        }

        return 0;
    }

    /**
     * 获取正在执行任务的设备
     * @return
     * @param deviceType
     */
    public List<String> getTaskingDevice(DeviceType deviceType) {
        List<String> taskingDevice = new ArrayList<>();

        if (deviceType == DeviceType.RGV4) {
            monitorInformation.getRgvs().values().forEach(rgvInformation -> {
                if (rgvInformation.getExecTaskTime() != null) {
                    taskingDevice.add(rgvInformation.getSeries());
                }
            });
        }

        return taskingDevice;
    }

    /**
     * 获取总货位数量
     * @return
     */
    public int getCargoSpaceNum() {
        return nodeDBService.getNodeByType(NodeType.P).size();
    }

    /**
     * 获取已使用的货位数量
     * @return
     */
    public int getUsedCargoSpaceNum() {
        return nodeDBService.getNodePUsedNum();
    }

    /**
     * 获取小车实时信息
     * @param series
     * @return
     */
    public RgvInfo getRgvInfo(String series) {
        RgvInformation rgvInformation = monitorInformation.getRgvs().get(series);
        if (rgvInformation == null) {
            return null;
        }

        return rgvInformation.getRgvInfo();
    }

    /**
     * 获取小车当天任务时间
     * @param series
     * @return
     */
    public long getTodayDeviceWorkTime(String series) {
        RgvInformation rgvInformation = monitorInformation.getRgvs().get(series);
        if (rgvInformation == null) {
            return 0;
        }

        return rgvInformation.getDeviceTaskInformation().getExecTodayTaskTime();
    }

    /**
     * 获取小车总的任务时间
     * @param series
     * @return
     */
    public long getDeviceWorkTime(String series) {
        RgvInformation rgvInformation = monitorInformation.getRgvs().get(series);
        if (rgvInformation == null) {
            return 0;
        }

        return rgvInformation.getDeviceTaskInformation().getExecAllTaskTime();
    }

    /**
     * 查找已完成的任务数量
     * @param taskType
     * @return
     */
    public int getFinishTaskNum(TaskType taskType) {
        return taskMonitor.getFinishTaskNum(taskType);
    }

    /**
     * 查找执行中的任务数量
     * @param taskType
     * @return
     */
    public int getExecingTaskNum(TaskType taskType) {
        return taskMonitor.getExecingTaskNum(taskType);
    }

    /**
     * 查找取消的任务数量
     * @param taskType
     * @return
     */
    public int getCancelTaskNum(TaskType taskType) {
        return taskMonitor.getCancelTaskNum(taskType);
    }

    /**
     * 查找故障的任务数量
     * @param taskType
     * @return
     */
    public int getErrorTaskNum(TaskType taskType) {
        return taskMonitor.getErrorTaskNum(taskType);
    }

    /**
     * 查找等待执行的任务数量
     * @param taskType
     * @return
     */
    public int getWaitForExecTaskNum(TaskType taskType) {
        return taskMonitor.getWaitForExecTaskNum(taskType);
    }
}
